#include "modbus_serialport.h"
// #define TEST_DATA
modbus_serialport::modbus_serialport(QObject *parent)
    : QObject(parent), modbusClient(new QModbusRtuSerialMaster(this))
{

    // 在构造函数中初始化定时器
    // jsonUpdateTimer.setInterval(1000); // 每隔 1 分钟触发
    // connect(&jsonUpdateTimer, &QTimer::timeout, this, &modbus_serialport::updateJsonAndSend);
    // 初始化定时器
    pollTimer.setInterval(1000);
    connect(&pollTimer, &QTimer::timeout, this, &modbus_serialport::onPollTimerTimeout);
}

void modbus_serialport::initializeModbusDevice(const QString &portName)
{
    // 断开之前的连接
    if (modbusClient->state() == QModbusDevice::ConnectedState)
    {
        modbusClient->disconnectDevice();
    }

    // 设置新的串口参数
    modbusClient->setConnectionParameter(QModbusDevice::SerialPortNameParameter, portName);
    modbusClient->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600);
    modbusClient->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
    modbusClient->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
    modbusClient->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
    // 重新连接设备
    connect(modbusClient, &QModbusClient::errorOccurred, this, &modbus_serialport::handleModbusError);
    if (!modbusClient->connectDevice())
    {
        emit signalToForward("Serial connection failed: " + modbusClient->errorString());
    }
    else
    {
        qDebug() << "Successfully connected to Modbus device on" << portName;
    }
}

void modbus_serialport::handleModbusError(QModbusDevice::Error error)
{
    QString errorMessage = modbusClient->errorString();
    // qWarning() << "Modbus error occurred:" << errorMessage;

    // 发送错误信息到外部
    emit signalToForward("Modbus error: " + errorMessage);
}
void modbus_serialport::onPollTimerTimeout()
{
    if (modbusClient->state() != QModbusDevice::ConnectedState)
    {
        // 如果未连接，不发送数据，但仍然更新索引以避免阻塞
        if (modbus_frames.size() > 0 && currentFrameIndex >= modbus_frames.size())
        {
            currentFrameIndex = 0;
            updateJsonAndSend(); // 即使未连接也投递数据（可能包含默认值"--"）
        }
        currentFrameIndex++;
        return;
    }
    else
    {
        sendNextFrame();
    }
}

void modbus_serialport::sendNextFrame()
{
    QMutexLocker framesLocker(&framesMutex); // 锁定 modbus_frames 的互斥锁
    QMutexLocker replyLocker(&replyMutex);   // 锁定 currentReply 的互斥锁

    if (modbus_frames.size() == 0)
    {
        return;
    }
    if (currentFrameIndex >= modbus_frames.size())
    {
        currentFrameIndex = 0; // 重置到第一帧
        // qDebug() << "send json";
        updateJsonAndSend(); // 投递一轮数据
    }

    if (currentReply && currentReply->isFinished())
    {
        currentReply->deleteLater();
        currentReply = nullptr;
    }

    if (!currentReply)
    {
        const ModbusFrame &frame = modbus_frames[currentFrameIndex];
        QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, frame.startId, frame.count);

        // 打印发送的请求信息
        // qDebug() << "Sending Modbus request - Start ID:" << frame.startId
        //          << "Register count:" << frame.count
        //          << "Slave address: 1";

        currentReply = modbusClient->sendReadRequest(readUnit, 1); // 假设从站地址为 1
        if (!currentReply)
        {
            qWarning() << "Failed to send Modbus request for frame" << frame.startId;
            currentFrameIndex++;
        }
        else
        {
            connect(currentReply, &QModbusReply::finished, this, &modbus_serialport::onModbusReplyFinished);
        }
    }
}

void modbus_serialport::onModbusReplyFinished()
{
    QMutexLocker locker(&replyMutex); // 锁定互斥锁
    if (!currentReply)
        return;

    if (currentReply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit unit = currentReply->result();
        const ModbusFrame &frame = modbus_frames[currentFrameIndex];
        if (frame.ids.size() != unit.valueCount())
        {
            qWarning() << "Mismatch between frame IDs and Modbus data values.";
            return;
        }

        // 打印接收到的响应信息
        // qDebug() << "Received Modbus response - Start ID:" << frame.startId
        //          << "Register count:" << unit.valueCount();

        for (int i = 0; i < frame.ids.size(); ++i)
        {
            int id = frame.ids[i];
            quint16 rawValue = unit.value(i); // 获取原始的无符号整数值

            // 打印原始数据
            // qDebug() << "Raw data for ID" << id << ":" << QString("0x%1").arg(rawValue, 4, 16, QLatin1Char('0'));

            if (rawValue == 0x8F00)
            {
                modbus_id_value_map[QString::number(id)] = "--"; // 标记为无效
                continue;
            }
            qint16 signedValue = static_cast<qint16>(rawValue); // 显式转换为有符号
            // 否则正常转换
            double floatValue = static_cast<double>(signedValue) / 100.0;
            QString value = QString::number(floatValue, 'f', 2); // 修改为一位小数
            modbus_id_value_map[QString::number(id)] = value;
        }

        // qDebug() << "Updated modbus_id_value_map with frame" << frame.startId;
    }
    else
    {
        // 处理错误情况：将当前帧对应的所有寄存器值设置为"--"
        const ModbusFrame &frame = modbus_frames[currentFrameIndex];
        for (int id : frame.ids)
        {
            modbus_id_value_map[QString::number(id)] = "--";
        }
        // qWarning() << "Modbus reply error:" << currentReply->errorString();
    }

    currentReply->deleteLater();
    currentReply = nullptr;
    currentFrameIndex++; // 切换到下一帧
}
/**
 * @brief modbus_serialport::processJsonCommand
 * 解析目的有二：
 * 1-生成一个modbus采集逻辑；
 * 2-采集回来的数据需要覆盖到这个json里并丢回去
 * @param jsonStr
 * @param err
 * @return
 */
bool modbus_serialport::processJsonCommand(const QString &jsonStr, QString *err)
{

    QMutexLocker locker(&framesMutex); // 锁定互斥锁
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8(), &error);

    if (error.error != QJsonParseError::NoError)
    {
        *err = "JSON analyse failed: " + error.errorString();
        return false;
    }

    QJsonObject root = doc.object();

    if (!root.contains("plugin_config"))
    {
        *err = "JSON format error: can not fine plugin_config seg";
        return false;
    }
    // // 检查 Modbus 客户端状态
    // if (modbusClient->state() != QModbusDevice::ConnectedState)
    // {
    //     emit signalToForward("Modbus client is not connected.");
    //     *err = "Modbus client is not connected.";
    //     return false;
    // }

    pollTimer.stop(); // 暂停定时器
    // jsonUpdateTimer.stop();
    modbus_json = jsonStr;
    modbus_id_value_map.clear();
    QJsonObject config = root["plugin_config"].toObject();
    int channalId = config["channal"].toString().toInt();
    QString uartChannalm = config["uartChannal"].toString();
    if (uartChannal != uartChannalm && uartChannalm != "")
    {
        // qDebug() << "Serial port changed from" << uartChannal << "to" << uartChannalm;
        uartChannal = uartChannalm;
        initializeModbusDevice(uartChannal); // 触发重新连接
    }
    QJsonArray blocksArray = config["blocks"].toArray();
    for (const QJsonValue &blockValue : blocksArray)
    {
        QJsonObject blockObj = blockValue.toObject();

        // 获取当前 block 的参数数组
        if (blockObj.contains("parameters"))
        {
            QJsonArray paramsArray = blockObj["parameters"].toArray();

            // 遍历当前 block 的所有参数
            for (const QJsonValue &paramValue : paramsArray)
            {
                QJsonObject paramObj = paramValue.toObject();

                // 提取 id 作为 key
                QString id = paramObj["modbusAddr"].toString();

                // 将 id 和空字符串存入 QMap
                modbus_id_value_map[id] = "--"; // 根据要求 value 暂存0
            }
        }
    }

    modbus_frames.clear();
    groupContinuousIDs(modbus_frames);    // 刷新帧内容
    writeChannelConfiguration(channalId); // 刷新信道

    pollTimer.start(1000); // 恢复定时器
    // jsonUpdateTimer.start(1000);
    return true;
}
void modbus_serialport::writeChannelConfiguration(int channalId)
{
    if (modbusClient->state() != QModbusDevice::ConnectedState)
    {
        qWarning() << "Modbus client not connected, cannot write channel configuration.";
        return;
    }

    quint16 registerAddress = 0xF000;                // 十六进制地址 f000
    quint16 value = static_cast<quint16>(channalId); // 转换为 16 位无符号整数
    QModbusDataUnit writeUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters,
                                                registerAddress, 1);
    writeUnit.setValue(0, value);

    // 打印发送的写请求信息
    // qDebug() << "Writing channel configuration - Register address: 0xF000"
    //  << "Value:" << value
    //  << "Slave address: 1";

    QModbusReply *reply = modbusClient->sendWriteRequest(writeUnit, 1);
    if (!reply)
    {
        qWarning() << "Failed to send write request for channel configuration.";
        return;
    }

    // 在 Lambda 中捕获 value 值
    connect(reply, &QModbusReply::finished, this, [this, reply, value]()
            {
        if (reply->error() == QModbusDevice::NoError)
        {
            // qDebug() << "[RESPONSE] Successfully wrote channel ID"
            //          << value
            //          << "to register address 0xF000.";
        }
        else
        {
            // qWarning() << "[ERROR] Failed to write channel ID:" << reply->errorString();
        }
        reply->deleteLater(); });
}
// 分组函数：将连续 ID 分组为 Modbus 帧
void modbus_serialport::groupContinuousIDs(QVector<ModbusFrame> &frames, int maxRegistersPerFrame)
{
    // 1. 提取键并转换为整数，然后排序
    QList<int> sortedIds;
    for (auto it = modbus_id_value_map.constBegin(); it != modbus_id_value_map.constEnd(); ++it)
    {
        bool ok;
        int id = it.key().toInt(&ok);
        if (ok)
        {
            sortedIds.append(id);
        }
    }

    // 3. 排序 ID 列表
    std::sort(sortedIds.begin(), sortedIds.end());

    // 移除了调试打印 sortedIds 的语句

    if (sortedIds.isEmpty())
    {
        return;
    }

    int start = sortedIds.first();
    int count = 1;
    QList<int> currentIds;
    currentIds.append(start);

    // 遍历排序后的 ID 列表
    for (int i = 1; i < sortedIds.size(); ++i)
    {
        int currentId = sortedIds[i];
        int previousId = sortedIds[i - 1];

        // 检查是否连续且未超过最大寄存器限制
        if (currentId == previousId + 1 && count < maxRegistersPerFrame)
        {
            count++;
            currentIds.append(currentId);
        }
        else
        {
            // 不连续或达到最大限制，创建新帧

            frames.append(ModbusFrame(start, count));
            frames.last().ids = currentIds;

            // 重置当前帧
            start = currentId;
            count = 1;
            currentIds.clear();
            currentIds.append(start);
        }
    }

    // 添加最后一个帧
    frames.append(ModbusFrame(start, count));
    frames.last().ids = currentIds;
}

/*****************************************************************
 * @brief : 定时投递数据给外面
 *****************************************************************/
void modbus_serialport::updateJsonAndSend()
{
#ifdef TEST_DATA
    QString updatedJson = modifyJsonData(modbus_json);
    emit signalToForward(updatedJson);
#else

    if (modbus_json.isEmpty())
    {
        qWarning() << "JSON string is empty, cannot update.";
        return;
    }

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(modbus_json.toUtf8(), &error);

    if (error.error != QJsonParseError::NoError)
    {
        qWarning() << "Failed to parse JSON for update:" << error.errorString();
        return;
    }

    QJsonObject root = doc.object();
    QJsonObject pluginConfig = root["plugin_config"].toObject();
    QJsonArray blocks = pluginConfig["blocks"].toArray();

    // 遍历所有block
    for (int i = 0; i < blocks.size(); ++i)
    {
        QJsonObject block = blocks[i].toObject();
        QJsonArray parameters = block["parameters"].toArray();

        // 遍历每个参数
        for (int j = 0; j < parameters.size(); ++j)
        {
            QJsonObject param = parameters[j].toObject();
            QString id = param["modbusAddr"].toString();
            QString type = param["type"].toString();

            if (modbus_id_value_map.contains(id))
            {
                param["data"] = modbus_id_value_map[id];
            }
            parameters[j] = param;
        }

        block["parameters"] = parameters;
        blocks[i] = block;
    }

    pluginConfig["blocks"] = blocks;
    // 关键修改：输出时使用 "plugin_data" 替代 "plugin_config"
    // 先移除旧的 "plugin_config" 节点
    root.remove("plugin_config");
    // 添加新的 "plugin_data" 节点
    root["plugin_data"] = pluginConfig;

    // 转换为字符串并通过信号发送
    QString updatedJson = QJsonDocument(root).toJson(QJsonDocument::Compact);

    // 打印发送的JSON数据
    // qDebug() << "Sending updated JSON data:" << updatedJson;

    emit signalToForward(updatedJson);
#endif
}

QString modbus_serialport::modifyJsonData(const QString &jsonInput)
{
    // 解析输入JSON
    QJsonDocument doc = QJsonDocument::fromJson(jsonInput.toUtf8());
    if (doc.isNull())
    {
        return "{}"; // 无效JSON返回空对象
    }

    QJsonObject root = doc.object();
    QJsonObject pluginConfig = root["plugin_config"].toObject();
    QJsonArray blocks = pluginConfig["blocks"].toArray();

    // 遍历所有block
    for (int i = 0; i < blocks.size(); ++i)
    {
        QJsonObject block = blocks[i].toObject();
        QJsonArray parameters = block["parameters"].toArray();

        // 遍历每个参数
        for (int j = 0; j < parameters.size(); ++j)
        {
            QJsonObject param = parameters[j].toObject();
            QString type = param["type"].toString();
            double randomValue = 0.0;

            // 根据类型生成随机数据
            if (type == "温度")
            {
                double min = 25.0;
                double max = 138.0;
                randomValue = min + QRandomGenerator::global()->generateDouble() * (max - min);
            }
            else if (type == "湿度")
            {
                double min = 40.0;
                double max = 99.0;
                randomValue = min + QRandomGenerator::global()->generateDouble() * (max - min);
            }
            else
            {
                randomValue = QRandomGenerator::global()->bounded(100);
            }

            // 格式化为字符串（保留1位小数）
            param["data"] = QString::number(randomValue, 'f', 2);
            parameters[j] = param;
        }

        block["parameters"] = parameters;
        blocks[i] = block;
    }

    pluginConfig["blocks"] = blocks;
    // root["plugin_config"] = pluginConfig;
    // 关键修改：输出时使用 "plugin_data" 替代 "plugin_config"
    // 先移除旧的 "plugin_config" 节点
    root.remove("plugin_config");
    // 添加新的 "plugin_data" 节点
    root["plugin_data"] = pluginConfig;
    // 返回格式化后的JSON字符串
    return QJsonDocument(root).toJson(QJsonDocument::Compact);
}